#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===============================================================================
# Copyright 2011 zod.yslin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 
# Author: zod.yslin
# Email: 
# File Name: classic.py
# Description: 
#   The concept of (old-style) class is unrelated to the concept of type: 
#   if x is an instance of an old-style class, then x.__class__ designates 
#   the class of x, but type(x) is always <type 'instance'>. 
#   This reflects the fact that all old-style instances, independently of 
#   their class, are implemented with a single built-in type, called instance.
#
#   classic.py vs. newstyle.py
#   mro() stands for Method Resolution Order. 
#   It returns a list of types the class is derived from, in the order they are searched for methods
# Edit History: 
#   2011-08-12    File created.
#===============================================================================
class classic:
    def __init__(self):
        print "classic"

c = classic()        
print type(c)
print c.__class__

# 在Python类的方法（method）中，要调用父类的某个方法，在Python 2.2以前,
# 使用非绑定的类方法（用类名来引用的方法），并在参数列表中，引入待绑定的对象（self），从而达到调用父类的目的
# 缺点是，当一个子类的父类发生变化时（如类B的父类由A变为C时），必须遍历整个类定义，把所有的通过非绑定的方法的类名全部替换过来
class A:
  def __init__(self):
   print "enter A"
   print "leave A"
class B(A):
  def __init__(self):
   print "enter B"
   A.__init__(self)
   print "leave B"

#b = B()


#   object
#      |  \
#      |    A
#      |   / |
#      B  C  D
#      \ /   |
#       E    |
#        \   |
#           F
class A(object):
    indent = ""
    def __init__(self):
        print A.indent + "A{"
        A.indent += "  "
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "A}"

class B(object):
    def __init__(self):
        print A.indent + "B{"
        A.indent += "  "
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "B}"
class C(A):
    """
    在调用类C的初始化函数时，应该是调用类A的初始化函数，但事实上却调用了类D的初始化函数。好一个诡异的问题！
    也就是说，mro中记录了一个类的所有基类的类类型序列。查看mro的记录，发觉包含7个元素，7个类名分别为：
        F E B C D A object
    从而说明了为什么在C.__init__中使用super(C, self).__init__()会调用类D的初始化函数了
    """
    def __init__(self):
        print A.indent + "C{"
        A.indent += "  "
        super(C, self).__init__()
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "C}"
class D(A):
    def __init__(self):
        print A.indent + "D{"
        A.indent += "  "
        super(D, self).__init__()
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "D}"
class E(B, C):
    def __init__(self):
        print A.indent + "E{"
        A.indent += "  "
        B.__init__(self)
        C.__init__(self)
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "E}"
class F(E, D):
    def __init__(self):
        print A.indent + "F{"
        A.indent += "  "
        E.__init__(self)
        D.__init__(self)
        A.indent = A.indent[0:len(A.indent)-2]
        print A.indent + "F}"

# 类A和类D的初始化函数被重复调用了2次，这并不是我们所期望的结果！
# 我们所期望的结果是最多只有类A的初始化函数被调用2次
f = F()
print F.__mro__
print f.__class__.mro()
